package main

import (
	"fmt"
	"git.oschina.net/dddailing/annotate/server"
	"github.com/dailing/levlog"
	"github.com/go-xorm/xorm"
	"io/ioutil"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

func Shuffle(a []string) {
	for i := range a {
		j := rand.Intn(i + 1)
		a[i], a[j] = a[j], a[i]
	}
}

func min(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func updateDB() {
	rand.Seed(time.Now().Unix())
	levlog.Info("start")
	content, err := ioutil.ReadFile("GradeResult.csv")
	levlog.E(err)
	ctstr := string(content)
	strs := strings.Split(ctstr, "\n")
	Shuffle(strs)
	levlog.Info(strs[0])

	engine, err := xorm.NewEngine("mysql", "root:123456@tcp(mysql)/"+server.DB_NAME)
	levlog.F(err)
	err = engine.Charset("utf8").Sync2(
		new(server.Image),
	)
	levlog.F(err)

	nameLevelMap := make(map[string]int)

	for _, str := range strs {
		fields := strings.Split(str, ",")
		name := fields[0]
		if str == "" {
			continue
		}
		grade, err := strconv.ParseInt(fields[1], 10, 64)
		//levlog.Info(str)
		if err != nil {
			levlog.Error(str)
		}
		levlog.E(err)

		nameLevelMap[name] = int(grade)
	}

	count, err := engine.Count(new(server.Image))
	levlog.E(err)
	levlog.Info(count)

	// var start int64 = 0
	var end int64 = 0
	const step = 500
	startChannel := make(chan int64, 0)

	addFunc := func() {
		for {
			var imgs []server.Image
			start := <-startChannel
			end = min(end, count)
			sqlstr := fmt.Sprintf("select * from image limit %d offset %d", step, start)
			levlog.Error(sqlstr)
			err := engine.SQL(sqlstr).Find(&imgs)
			levlog.E(err)
			for _, img := range imgs {
				img.Grade = nameLevelMap[img.Path]
				if img.Grade == 0 {
					continue
				}
				levlog.Info(start, " ", step, " updating ", img.Id, " : ", img.Path, " to ", img.Grade)
				engine.Id(img.Id).Cols("grade").Update(&img)
				// engine.Cols("id", "grade").Update(img)
			}
		}
	}

	for i := 0; i < 20; i += 1 {
		go addFunc()
	}

	for start := int64(0); start < count; start += step {
		startChannel <- start
		levlog.Info("Put in to CHannel", start)
	}
	levlog.Info("Finished")
	for i := 20; i >= 0; i -= 1 {
		levlog.Info(i)
		time.Sleep(time.Second)
	}
}
